2. 쿠버네티스 개요1

3.1. 쿠버네티스의 특징

3.1.1. 파일을 사용한 선언적 관리

선언적 관리란?

쿠버네티스의 주요 특징은 선언적으로 애플리케이션을 관리할 수 있다는 것

용어 정리

  • 선언적 관리(Declarative Management): "원하는 최종 상태"를 정의하면 시스템이 자동으로 그 상태를 유지하는 방식
  • 명령형(Imperative): 수행할 작업을 단계별로 직접 명령하는 방식. 예: "컨테이너를 생성하라"
  • 선언형(Declarative): 원하는 결과 상태만 선언하는 방식. 예: "컨테이너가 3개 있어야 한다"

선언적 관리 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[명령형 (Imperative)]
    "어떻게(How)"를 명령
    ├─ 컨테이너 3개 생성하라
    ├─ 포트 80을 열어라
    └─ 볼륨을 연결하라

    문제점: 상태 추적 어려움, 재현 어려움

vs

[선언형 (Declarative)]
    "무엇을(What)"을 선언
    ├─ 컨테이너는 3개여야 함
    ├─ 포트 80이 열려있어야 함
    └─ 볼륨이 연결되어 있어야 함

    장점: 상태 자동 유지, Git 버전 관리 가능

매니페스트 파일 (Manifest):

쿠버네티스에서 애플리케이션의 이상적인 상태를 YAML 또는 JSON 형식의 파일로 선언

용어 정리

  • 매니페스트(Manifest): Kubernetes 리소스의 원하는 상태를 정의하는 YAML 또는 JSON 파일
  • YAML: 사람이 읽기 쉬운 데이터 직렬화 형식. 들여쓰기로 계층 구조 표현
  • replicas: 동시에 실행할 Pod 복제본의 개수

매니페스트 파일 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[매니페스트 파일]
    │
    ├─ 컨테이너 개수
    │  └─ replicas: 3
    │
    ├─ 배포 형식
    │  └─ kind: Deployment
    │
    ├─ 이미지 정보
    │  └─ image: nginx:1.21
    │
    ├─ 네트워크 설정
    │  └─ ports, services
    │
    └─ 스토리지 설정
       └─ volumes, persistentVolumes

선언적 관리의 장점:

파일 기반 관리 장점:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Git 버전 관리
    │
    ├─ 변경 이력 추적
    ├─ 롤백 용이
    └─ 팀 협업 가능
    ↓

재현 가능성
    │
    ├─ 동일 환경 구축
    ├─ 개발/스테이징/프로덕션 일관성
    └─ 장애 복구 신속
    ↓

자동화
    │
    ├─ CI/CD 파이프라인 통합
    ├─ GitOps 워크플로우
    └─ Infrastructure as Code (IaC)
용어 정리

  • CI/CD(Continuous Integration/Continuous Delivery): 코드 변경을 자동으로 빌드, 테스트, 배포하는 소프트웨어 개발 방식
  • GitOps: Git 저장소를 단일 진실 공급원(Single Source of Truth)으로 사용하여 인프라와 애플리케이션을 관리하는 방식
  • IaC(Infrastructure as Code): 인프라 구성을 코드로 정의하고 관리하는 방식. 재현성과 버전 관리 가능


3.1.2. 광범위한 배포 형식 지원

다양한 워크로드 타입:

쿠버네티스는 컨테이너와 관련된 다양한 배포 형식을 지원

용어 정리

  • 워크로드(Workload): 쿠버네티스에서 실행되는 애플리케이션의 유형. Deployment, StatefulSet, DaemonSet, Job 등
  • Stateless: 상태를 저장하지 않는 애플리케이션. 어떤 인스턴스가 요청을 처리해도 결과 동일
  • Stateful: 상태를 유지해야 하는 애플리케이션. 데이터베이스처럼 영구 저장소와 고유 식별자 필요

쿠버네티스 워크로드 타입:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Stateless 애플리케이션]
    │
    Deployment
    ├─ 웹 서버 (nginx, Apache)
    ├─ API 서버
    └─ 정적 마이크로서비스

    특징: 데이터 영구 보존 불필요

[Stateful 애플리케이션]
    │
    StatefulSet
    ├─ 데이터베이스 (MySQL, PostgreSQL)
    ├─ 메시지 큐 (Kafka, RabbitMQ)
    └─ 분산 스토리지

    특징: 고유 식별자, 영구 스토리지 필요

[데몬 프로세스]
    │
    DaemonSet
    ├─ 로그 수집 (Fluentd)
    ├─ 모니터링 (Prometheus Node Exporter)
    └─ 네트워크 플러그인

    특징: 모든 노드에서 실행

[배치 작업]
    │
    Job / CronJob
    ├─ 데이터 백업
    ├─ ETL 작업
    └─ 정기 스크립트 실행

    특징: 완료 후 종료, 스케줄 실행
용어 정리

  • StatefulSet(스테이트풀셋): 상태 유지가 필요한 애플리케이션을 위한 컨트롤러. 고유한 네트워크 ID와 영구 스토리지 제공
  • DaemonSet(데몬셋): 클러스터의 모든(또는 일부) 노드에 Pod를 하나씩 실행하는 컨트롤러
  • Job: 한 번 실행 후 완료되는 배치 작업을 관리하는 컨트롤러
  • CronJob: Job을 주기적으로 스케줄링하여 실행하는 컨트롤러. Linux cron과 유사

자동화된 관리 기능:

쿠버네티스 자동 관리:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[자동 복구 (Self-Healing)]
    │
    ├─ 컨테이너 크래시 감지 → 자동 재시작
    ├─ 노드 장애 감지 → 다른 노드로 재배치
    └─ Health Check 실패 → Pod 교체
    ↓

[자동 스케일링 (Auto-Scaling)]
    │
    ├─ HPA (Horizontal Pod Autoscaler)
    │  └─ CPU/메모리 사용률 기반 Pod 수 조정
    │
    ├─ VPA (Vertical Pod Autoscaler)
    │  └─ 리소스 요구량 자동 조정
    │
    └─ Cluster Autoscaler
       └─ 노드 수 자동 조정
    ↓

[롤링 업데이트 (Rolling Update)]
    │
    ├─ 무중단 배포
    ├─ 점진적 업데이트
    └─ 자동 롤백 (실패 시)
용어 정리

  • Self-Healing(자동 복구): 컨테이너 장애 시 자동으로 재시작하고, 노드 장애 시 다른 노드로 Pod를 재배치하는 기능
  • HPA(Horizontal Pod Autoscaler): CPU/메모리 사용률 등 메트릭에 따라 Pod 수를 자동으로 조절
  • VPA(Vertical Pod Autoscaler): Pod의 CPU/메모리 요청량을 자동으로 조절
  • Rolling Update(롤링 업데이트): 서비스 중단 없이 점진적으로 새 버전을 배포하는 방식
  • 롤백(Rollback): 배포 실패 시 이전 버전으로 되돌리는 작업


3.1.3. 확장성이 뛰어난 아키텍처

쿠버네티스 확장 메커니즘:

쿠버네티스 확장 아키텍처:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[API 서버 (kube-apiserver)]
    │
    HTTP REST API 제공
    │
    ├─ 클러스터 상태 조회
    ├─ 리소스 생성/수정/삭제
    └─ 이벤트 모니터링 (Watch)
    ↓

[컨트롤러 (Controller)]
    │
    API 감시 + 상태 조정
    │
    ├─ 기본 컨트롤러
    │  ├─ Deployment Controller
    │  ├─ ReplicaSet Controller
    │  └─ Service Controller
    │
    └─ 커스텀 컨트롤러
       ├─ Operator Pattern
       ├─ 서드파티 컨트롤러
       └─ 사용자 정의 컨트롤러
    ↓

[커스텀 리소스 (CRD)]
    │
    API 확장
    │
    ├─ 새로운 리소스 타입 정의
    ├─ 도메인 특화 객체 관리
    └─ 커스텀 컨트롤러와 연동
용어 정리

  • 컨트롤러(Controller): 클러스터 상태를 감시하고 현재 상태를 원하는 상태로 조정하는 컴포넌트
  • Watch: API 서버의 리소스 변경을 실시간으로 감시하는 메커니즘
  • CRD(Custom Resource Definition): 사용자가 새로운 리소스 타입을 정의할 수 있게 해주는 Kubernetes 확장 메커니즘
  • Operator Pattern: CRD와 커스텀 컨트롤러를 조합하여 복잡한 애플리케이션을 자동 관리하는 패턴

확장 가능한 컴포넌트:

교체 가능한 컴포넌트:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[컨테이너 런타임]
    ├─ containerd (권장)
    ├─ CRI-O
    └─ Docker Engine (deprecated)

[네트워크 플러그인 (CNI)]
    ├─ Calico
    ├─ Flannel
    ├─ Cilium
    └─ Weave Net

[스토리지 플러그인 (CSI)]
    ├─ AWS EBS
    ├─ GCE Persistent Disk
    ├─ Azure Disk
    └─ Ceph, NFS

[인그레스 컨트롤러]
    ├─ NGINX Ingress Controller
    ├─ Traefik
    ├─ HAProxy
    └─ 클라우드 제공업체 LB
용어 정리

  • CNI(Container Network Interface): 컨테이너 네트워킹을 위한 표준 인터페이스. Calico, Flannel, Cilium 등 다양한 플러그인 존재
  • CSI(Container Storage Interface): 컨테이너 스토리지를 위한 표준 인터페이스. 클라우드 스토리지와 쉽게 연동
  • Ingress(인그레스): 클러스터 외부에서 내부 서비스로의 HTTP/HTTPS 라우팅을 관리하는 리소스
  • Ingress Controller: Ingress 리소스의 규칙을 실제로 구현하는 컨트롤러. NGINX, Traefik 등

CNCF 생태계:

쿠버네티스는 Cloud Native Computing Foundation (CNCF)을 중심으로 개발된 오픈소스 프로젝트

CNCF 프로젝트 생태계:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[서비스 메시]
    ├─ Istio
    ├─ Linkerd
    └─ Consul

[모니터링/관찰성]
    ├─ Prometheus
    ├─ Grafana
    ├─ Jaeger
    └─ Fluentd

[보안]
    ├─ Falco
    ├─ Open Policy Agent (OPA)
    └─ cert-manager

[CI/CD]
    ├─ Argo CD
    ├─ Flux
    └─ Tekton

[클러스터 관리]
    ├─ Rancher
    ├─ Kubeadm
    └─ kops
용어 정리

  • CNCF(Cloud Native Computing Foundation): 클라우드 네이티브 기술의 발전을 위한 오픈소스 재단. Kubernetes 호스팅
  • 서비스 메시(Service Mesh): 마이크로서비스 간 통신을 관리하는 인프라 계층. 트래픽 관리, 보안, 관찰성 제공
  • Prometheus: 메트릭 수집과 알림을 위한 오픈소스 모니터링 시스템
  • Grafana: 메트릭 데이터를 시각화하는 대시보드 도구
  • cert-manager: Kubernetes에서 TLS 인증서를 자동으로 관리하는 도구


3.2. 쿠버네티스 클러스터와 kubectl

쿠버네티스 클러스터 아키텍처

클러스터 전체 구조:

Pasted image 20260111214405.png

주요 컴포넌트 설명:

컴포넌트 역할 위치
kube-apiserver 클러스터 관리 API 제공 Control Plane
etcd 클러스터 상태 데이터 저장 Control Plane
kube-scheduler Pod를 적절한 노드에 배치 Control Plane
kube-controller 리소스 상태 감시 및 조정 Control Plane
kubelet 노드에서 Pod 실행 관리 Worker Node
kube-proxy 네트워크 라우팅 및 로드밸런싱 Worker Node
Container Runtime 실제 컨테이너 실행 (containerd, CRI-O) Worker Node
용어 정리

  • kubelet(큐블릿): 각 워커 노드에서 실행되며, Pod의 컨테이너가 정상 실행되도록 관리하는 에이전트
  • kube-proxy(큐브 프록시): 각 노드에서 네트워크 규칙을 관리하고 서비스로의 트래픽을 Pod로 전달
  • Container Runtime(컨테이너 런타임): 컨테이너를 실제로 실행하는 소프트웨어. containerd, CRI-O 등


kubectl 명령줄 도구

kubectl이란?

쿠버네티스 클러스터를 조작하고 정보를 조회하기 위한 명령줄 인터페이스 (CLI)

kubectl 작동 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[사용자]
    │
    │ kubectl create deployment nginx --image=nginx
    ↓
[kubectl CLI]
    │
    │ HTTP REST API 요청 생성
    │ - POST /apis/apps/v1/namespaces/default/deployments
    ↓
[kube-apiserver]
    │
    │ 요청 처리
    │ - 인증/인가
    │ - etcd에 저장
    ↓
[컨트롤러]
    │
    │ API 변경 감지 (Watch)
    │ - Deployment Controller 동작
    │ - ReplicaSet 생성
    ↓
[Scheduler]
    │
    │ Pod 스케줄링
    │ - 적절한 노드 선택
    ↓
[Kubelet (Worker Node)]
    │
    │ Pod 실행
    │ - 컨테이너 생성

3.2.1. kubectl 기본 사용법

명령형 방식 (Imperative)

Deployment 생성:

# Deployment 생성
kubectl create deployment nginx-deployment --image=nginx

# 단축어 사용 (alias k='kubectl' 설정 후)
k create deployment nginx-deployment --image=nginx

# 자동완성 사용
k cr<Tab> de<Tab> nginx-deployment --image=nginx

출력 예시:

deployment.apps/nginx-deployment created

Deployment 상태 확인:

# Deployment 목록 조회
kubectl get deployments

# 축약형
kubectl get deploy

# 더 많은 정보 출력
kubectl get deployments -o wide

출력 예시:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   1/1     1            1           10s

Pod 상태 확인:

# Pod 목록 조회
kubectl get pods

# 축약형
kubectl get po

출력 예시:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7d64f8d4c9-xxxxx   1/1     Running   0          15s

리소스 삭제:

# Deployment 삭제
kubectl delete deployment nginx-deployment

출력 예시:

deployment.apps "nginx-deployment" deleted

선언형 방식 (Declarative)

매니페스트 파일 작성:

파일명: nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

매니페스트 구조 설명:

매니페스트 필드:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

apiVersion: apps/v1
    └─ 사용할 API 버전

kind: Deployment
    └─ 리소스 타입 (Deployment, Service, Pod 등)

metadata:
    └─ 리소스 메타정보
       ├─ name: 리소스 이름
       ├─ labels: 레이블 (key-value)
       └─ namespace: 네임스페이스

spec:
    └─ 리소스 상세 사양
       ├─ replicas: Pod 개수
       ├─ selector: Pod 선택 기준
       └─ template: Pod 템플릿
          ├─ metadata: Pod 메타정보
          └─ spec: Pod 사양
             ├─ containers: 컨테이너 목록
             ├─ volumes: 볼륨 목록
             └─ nodeSelector: 노드 선택

매니페스트 적용:

# 매니페스트 파일 적용
kubectl apply -f nginx-deployment.yaml

# 여러 파일 동시 적용
kubectl apply -f deployment.yaml -f service.yaml

# 디렉터리 전체 적용
kubectl apply -f ./manifests/

출력 예시:

deployment.apps/nginx-deployment created

리소스 상태 확인:

# 적용된 Deployment 확인
kubectl get deployment nginx-deployment

# YAML 형식으로 출력
kubectl get deployment nginx-deployment -o yaml

# JSON 형식으로 출력
kubectl get deployment nginx-deployment -o json

# 상세 정보 확인
kubectl describe deployment nginx-deployment

3.2.2. 쿠버네티스 자동 관리

자동 복구 (Self-Healing):

쿠버네티스는 적용한 설정에 따라 클러스터 상태를 자동으로 유지

자동 복구 시나리오:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[상황 1: Pod 크래시]
    │
    컨테이너 비정상 종료
    ↓
    kubelet 감지
    ↓
    컨테이너 자동 재시작
    ↓
    상태 복구

[상황 2: 노드 장애]
    │
    Node 1 다운
    ├─ Pod A (실행 중)
    └─ Pod B (실행 중)
    ↓
    Control Plane 감지 (약 5분)
    ↓
    Node 2, 3으로 Pod 재배치
    ├─ Pod A → Node 2
    └─ Pod B → Node 3
    ↓
    상태 복구

[상황 3: replicas 불일치]
    │
    설정: replicas: 3
    현재: 실행 중인 Pod 2개
    ↓
    ReplicaSet Controller 감지
    ↓
    부족한 1개 Pod 생성
    ↓
    상태 복구

실습 예시:

# replicas 3으로 설정
kubectl scale deployment nginx-deployment --replicas=3

# Pod 확인 (3개 실행 중)
kubectl get pods

# Pod 하나 강제 삭제
kubectl delete pod nginx-deployment-xxxxx

# 즉시 새로운 Pod 생성됨 (자동 복구)
kubectl get pods

출력 예시:

# 삭제 전
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7d64f8d4c9-abc12   1/1     Running   0          2m
nginx-deployment-7d64f8d4c9-def34   1/1     Running   0          2m
nginx-deployment-7d64f8d4c9-ghi56   1/1     Running   0          2m

# 삭제 후 (자동으로 새 Pod 생성됨)
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7d64f8d4c9-def34   1/1     Running   0          2m
nginx-deployment-7d64f8d4c9-ghi56   1/1     Running   0          2m
nginx-deployment-7d64f8d4c9-jkl78   1/1     Running   0          5s

3.2.3. 명령형 vs 선언형 비교

두 방식의 차이:

항목 명령형 (Imperative) 선언형 (Declarative)
명령어 create, run, expose, scale apply
특징 "어떻게" 할지 지시 "무엇을" 원하는지 선언
버전 관리 어려움 Git으로 쉽게 관리
재현성 낮음 높음
학습 난이도 쉬움 보통
프로덕션 비권장 권장
용도 빠른 테스트, 디버깅 프로덕션 배포, 자동화

권장 워크플로우:

개발 워크플로우:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[개발/테스트 단계]
    │
    명령형 방식으로 빠른 실험
    ├─ kubectl run nginx --image=nginx
    ├─ kubectl expose pod nginx --port=80
    └─ 빠른 반복 테스트
    ↓

[확정 후 매니페스트 작성]
    │
    선언형 파일로 정리
    ├─ deployment.yaml
    ├─ service.yaml
    └─ Git에 커밋
    ↓

[프로덕션 배포]
    │
    매니페스트 기반 배포
    ├─ kubectl apply -f ./manifests/
    ├─ GitOps 워크플로우
    └─ 자동 배포 파이프라인

3.3. 쿠버네티스의 기본 배포 단위: Pod

Pod란?

도커 vs 쿠버네티스 배포 단위:

배포 단위 비교:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Docker]
    기본 단위: 컨테이너
    ├─ 컨테이너 1개 = 애플리케이션 1개
    └─ 개별 관리

vs

[Kubernetes]
    기본 단위: Pod
    ├─ Pod 1개 = 컨테이너 1개 이상
    ├─ 관련 컨테이너 그룹화
    └─ 통합 관리

쿠버네티스에서 애플리케이션은 도커와 마찬가지로 컨테이너로 실행되지만, 가장 기본적인 배포 단위는 Pod (파드)

Pod의 정의:


3.3.1. Pod와 컨테이너

Pod 내부 구조:

Pod 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

┌─────────────────────────────────────┐
│            Pod (10.1.0.5)            │  ← Pod IP 주소
│                                      │
│  ┌────────────┐    ┌─────────────┐  │
│  │ Container1 │    │ Container2  │  │
│  │  (nginx)   │    │  (alpine)   │  │
│  │            │    │             │  │
│  │ Port: 80   │◄───┤ localhost   │  │  ← localhost 통신
│  └─────┬──────┘    └──────┬──────┘  │
│        │                  │         │
│        └──────────┬───────┘         │
│                   │                 │
│         ┌─────────▼─────────┐       │
│         │   공유 볼륨        │       │  ← 볼륨 공유
│         │   (emptyDir)      │       │
│         └───────────────────┘       │
│                                      │
└──────────────────────────────────────┘
         │
         │ 네트워크 통신
         ▼
   다른 Pod (10.1.0.6)

Pod의 특징:

항목 설명
배포 위치 동일한 노드에 함께 배포
네트워크 Pod마다 고유 IP 주소 할당
컨테이너 간 통신 동일 Pod 내 컨테이너는 localhost로 통신
Pod 간 통신 각 Pod의 IP 주소로 통신
스토리지 볼륨을 컨테이너 간 공유 가능

멀티 컨테이너 Pod 예제

매니페스트 파일:

파일명: pod-example.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    # 컨테이너 1: nginx 웹 서버
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80
      volumeMounts:
        - mountPath: /usr/share/nginx/html/
          name: docroot

    # 컨테이너 2: 데이터 생성
    - name: alpine
      image: alpine:3.18
      command: ["sh"]
      args:
        - -euc
        - |
          for i in $(seq 1 10) ; do
            echo '{"date": "'$(date)'"}' >> /mnt/date.json
            sleep 3
          done ; sleep infinity
      volumeMounts:
        - mountPath: /mnt/
          name: docroot

  # 컨테이너 간 공유 볼륨
  volumes:
    - name: docroot
      emptyDir:
        sizeLimit: 500Mi

emptyDir 볼륨이란?

용어 정리

  • emptyDir: Pod가 노드에 할당될 때 생성되는 임시 볼륨. Pod 삭제 시 데이터도 함께 삭제
  • 볼륨(Volume): Pod 내 컨테이너가 데이터를 저장하거나 공유할 수 있는 디렉터리
  • volumeMounts: 컨테이너 내부의 어떤 경로에 볼륨을 마운트할지 지정

emptyDir 볼륨 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Worker Node 호스트]
    │
    /var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~empty-dir/docroot/
    │
    ├─ Pod 생성 시 자동으로 빈 디렉터리 생성
    ├─ Pod 내 모든 컨테이너가 동일 경로 공유
    └─ Pod 삭제 시 볼륨 데이터도 함께 삭제
    ↓

[Pod 내부 마운트]
    │
    nginx 컨테이너: /usr/share/nginx/html/ → 호스트의 docroot 디렉터리
    alpine 컨테이너: /mnt/ → 호스트의 docroot 디렉터리
    │
    └─ 동일한 호스트 디렉터리를 서로 다른 경로로 마운트

emptyDir 특징:

항목 설명
생성 시점 Pod 생성 시 자동 생성
삭제 시점 Pod 삭제 시 자동 삭제 (임시 저장소)
저장 위치 Worker Node의 /var/lib/kubelet/pods/ 아래
공유 범위 동일 Pod 내 모든 컨테이너
용도 임시 파일, 캐시, 컨테이너 간 데이터 전달
영구성 없음 (Pod 재시작 시 데이터 손실)

볼륨 이름 (docroot):


동작 방식:

멀티 컨테이너 Pod 동작:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Worker Node 호스트]
    │
    /var/lib/kubelet/pods/abc123/volumes/.../docroot/
    │
    ↓

[alpine 컨테이너]
    │
    │ 타임스탬프 생성
    │ echo '{"date": "..."}' >> /mnt/date.json
    │ (실제로는 호스트의 docroot/date.json에 저장)
    ↓
[공유 볼륨 (docroot)]
    │
    │ 파일 공유
    │ date.json 파일이 두 컨테이너에 동시 접근 가능
    ↓
[nginx 컨테이너]
    │
    │ HTTP 서버로 파일 공개
    │ /usr/share/nginx/html/date.json 읽기
    │ (실제로는 호스트의 docroot/date.json 읽기)
    │ localhost:80/date.json
    ↓
[외부 접근]
    │
    │ Pod IP:80/date.json

실습 명령어:

# Pod 생성
kubectl apply -f pod-example.yaml

# Pod 확인
kubectl get pods

Windows (PowerShell):

# alpine 컨테이너에서 nginx로 접근 후 처음 3줄만 출력
kubectl exec -it example-pod -c alpine -- wget -qO - localhost:80/date.json | Select-Object -First 3

# 또는 더 간단하게
kubectl exec example-pod -c alpine -- wget -qO - localhost:80/date.json | Select-Object -First 3

macOS / Linux (Bash):

# alpine 컨테이너에서 nginx로 접근 후 처음 3줄만 출력
kubectl exec -it example-pod -c alpine -- wget -qO - localhost:80/date.json | head -n 3

# 또는
kubectl exec example-pod -c alpine -- wget -qO - localhost:80/date.json | head -3

출력 예시:

{"date": "Sat Jan 11 12:00:00 UTC 2026"}
{"date": "Sat Jan 11 12:00:03 UTC 2026"}
{"date": "Sat Jan 11 12:00:06 UTC 2026"}

명령어 옵션 상세 설명:

kubectl exec 명령어 분석:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

kubectl exec
    └─ Pod 내부 컨테이너에서 명령 실행

-it
    ├─ -i (--stdin): 표준 입력(stdin)을 유지하여 대화형 실행
    └─ -t (--tty): 터미널(TTY) 할당 (대화형 셸 사용 시 필수)
    └─ 참고: 단순 명령 실행 시 -it 생략 가능

example-pod
    └─ Pod 이름

-c alpine
    ├─ -c (--container): 컨테이너 이름 지정
    └─ 멀티 컨테이너 Pod에서 필수 (단일 컨테이너면 생략 가능)

--
    └─ kubectl 옵션과 컨테이너 내부 명령 구분

wget -qO - localhost:80/date.json
    ├─ wget: 파일 다운로드 도구
    ├─ -q (--quiet): 진행 상황 메시지 숨김
    ├─ -O - (--output-document=-): 표준 출력(stdout)으로 출력
    └─ localhost:80/date.json: 다운로드 URL

| (파이프)
    └─ 앞 명령의 출력을 뒤 명령의 입력으로 전달

Windows: Select-Object -First 3
    └─ 처음 3줄만 선택하여 출력

Linux: head -n 3
    └─ 처음 3줄만 출력 (-n 3 또는 -3)

Pod 삭제:

kubectl delete -f pod-example.yaml

참고:


Pod 디자인 패턴

1개 Pod에 여러 컨테이너를 배치하는 디자인 패턴:

Pod 디자인 패턴:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[사이드카 패턴 (Sidecar)]
    ┌─────────────────────────┐
    │         Pod             │
    │  ┌────────┐  ┌────────┐ │
    │  │  Main  │  │Sidecar │ │
    │  │  App   │◄─┤ 로그   │ │
    │  │        │  │ 수집   │ │
    │  └────────┘  └────────┘ │
    └─────────────────────────┘

    용도:
    ├─ 로그 수집 (Fluentd)
    ├─ Git 동기화
    └─ 모니터링 에이전트

[앰배서더 패턴 (Ambassador)]
    ┌─────────────────────────┐
    │         Pod             │
    │  ┌────────┐  ┌────────┐ │
    │  │  App   │─►│ Proxy  │ │
    │  │        │  │        │─┼─► 외부 서비스
    │  └────────┘  └────────┘ │
    └─────────────────────────┘

    용도:
    ├─ DB 프록시
    ├─ API 게이트웨이
    └─ 서비스 메시 프록시

[어댑터 패턴 (Adapter)]
    ┌─────────────────────────┐
    │         Pod             │
    │  ┌────────┐  ┌────────┐ │
    │  │  App   │─►│Adapter │─┼─► 표준화된 출력
    │  │        │  │        │ │
    │  └────────┘  └────────┘ │
    └─────────────────────────┘

    용도:
    ├─ 로그 형식 변환
    ├─ 메트릭 표준화
    └─ 데이터 변환

패턴별 사용 사례:

패턴 설명 예시
사이드카 메인 컨테이너 기능 확장 로그 수집, Git 동기화
앰배서더 외부 서비스 접근을 대신 처리 DB 프록시, 서비스 디스커버리
어댑터 출력 형식을 표준화하여 외부 제공 로그 포맷 변환, 메트릭 형식 통일화
용어 정리

  • 사이드카 패턴(Sidecar Pattern): 메인 컨테이너를 보조하는 컨테이너를 같은 Pod에 배치. 로그 수집, 프록시 등에 활용
  • 앰배서더 패턴(Ambassador Pattern): 외부 서비스와의 통신을 대리하는 컨테이너 배치. DB 연결 풀링 등
  • 어댑터 패턴(Adapter Pattern): 메인 컨테이너의 출력을 표준 형식으로 변환하는 컨테이너 배치


3.3.2. Label과 Annotation

대규모 리소스 관리:

대규모 서비스에서는 Pod와 관리 대상이 수백 개 이상으로 증가하므로 그룹화 및 메타데이터 부여 필요

용어 정리

  • Label(레이블): 리소스를 식별하고 그룹화하기 위한 키-값 쌍. Selector로 선택 가능
  • Annotation(애너테이션): 리소스에 추가 메타데이터를 부여하는 키-값 쌍. Selector 사용 불가
  • Selector(셀렉터): 레이블을 기준으로 리소스를 선택하는 쿼리 메커니즘

리소스 관리 메커니즘:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Label (레이블)]
    │
    키-값 쌍으로 리소스 식별
    │
    ├─ app: nginx
    ├─ env: production
    └─ tier: frontend
    ↓
[Selector (셀렉터)]
    │
    레이블 기반으로 리소스 선택
    │
    matchLabels:
      app: nginx
    ↓
[리소스 그룹화]
    │
    선택된 Pod들을 하나의 Deployment로 관리

vs

[Annotation (애너테이션)]
    │
    키-값 쌍으로 추가 정보 부여
    │
    ├─ kubernetes.io/change-cause: "Update to v2.0"
    ├─ prometheus.io/scrape: "true"
    └─ description: "Production web server"
    ↓
    Selector 사용 불가
    ↓
    메타데이터 및 도구 설정용

Label vs Annotation:

항목 Label (레이블) Annotation (애너테이션)
형식 키-값 쌍 키-값 쌍
Selector 사용 가능 사용 불가
용도 리소스 식별, 그룹화 메타데이터, 도구 설정
예시 app: nginx, env: prod description: "...", build: "12"
크기 제한 63자 (값) 제한 없음

Deployment와 Selector의 관계

Deployment가 Selector를 사용하는 이유:

Deployment는 Pod를 직접 생성하지 않고, ReplicaSet을 통해 Pod를 관리함. Selector는 "어떤 Pod들을 내가 관리할 것인가"를 정의하는 핵심 메커니즘

Deployment와 Selector 동작:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Deployment]
    │
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx          ← "app=nginx 레이블을 가진 Pod를 관리"
    │
    ├─ Deployment Controller가 ReplicaSet 생성
    │
    ↓

[ReplicaSet]
    │
    │ Deployment의 Selector 상속
    │ selector: app=nginx
    │
    ├─ "app=nginx" 레이블을 가진 Pod를 찾음
    ├─ 현재 개수 확인: 1개 존재
    ├─ 목표 개수: 3개 (replicas: 3)
    └─ 부족한 2개 Pod 생성
    ↓

[Pod 생성]
    │
    template:
      metadata:
        labels:
          app: nginx        ← 생성되는 Pod에 자동으로 레이블 부여
    │
    └─ 3개의 Pod 모두 "app=nginx" 레이블 보유
    ↓

[지속적인 관리]
    │
    ├─ Pod 1개 삭제됨 → ReplicaSet이 감지
    ├─ "app=nginx" 레이블을 가진 Pod 개수 확인: 2개
    ├─ 목표 개수 3개와 불일치
    └─ 부족한 1개 자동 생성

실제 동작 예시:

상황 1: Pod 수동 삭제
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[현재 상태]
Pod A: labels: {app: nginx}  ✓
Pod B: labels: {app: nginx}  ✓
Pod C: labels: {app: nginx}  ✓
→ 총 3개 (목표 3개 일치)

[사용자가 Pod B 삭제]
$ kubectl delete pod nginx-deployment-xxx-B

[ReplicaSet Controller 동작]
1. "app=nginx" 레이블을 가진 Pod 검색
2. 현재 개수: 2개 발견
3. 목표 개수: 3개 (replicas: 3)
4. → 새로운 Pod D 자동 생성 (labels: {app: nginx})

[최종 상태]
Pod A: labels: {app: nginx}  ✓
Pod C: labels: {app: nginx}  ✓
Pod D: labels: {app: nginx}  ✓ (새로 생성)
→ 총 3개 복구
상황 2: 레이블 변경
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[현재 상태]
Pod A: labels: {app: nginx}  ✓
Pod B: labels: {app: nginx}  ✓
Pod C: labels: {app: nginx}  ✓

[사용자가 Pod B의 레이블 변경]
$ kubectl label pod nginx-deployment-xxx-B app=web --overwrite

[ReplicaSet Controller 동작]
1. "app=nginx" 레이블을 가진 Pod 검색
2. 현재 개수: 2개 (Pod A, C만 해당)
3. 목표 개수: 3개
4. → 새로운 Pod D 자동 생성

[최종 상태]
Pod A: labels: {app: nginx}  ✓ (관리됨)
Pod B: labels: {app: web}    ✗ (관리 제외됨, 계속 실행)
Pod C: labels: {app: nginx}  ✓ (관리됨)
Pod D: labels: {app: nginx}  ✓ (새로 생성, 관리됨)
→ app=nginx: 3개, app=web: 1개

Selector의 핵심 역할:

역할 설명
Pod 식별 수많은 Pod 중 어떤 것을 관리할지 식별
동적 관리 레이블이 일치하는 Pod 개수를 지속적으로 모니터링
자동 복구 Pod가 삭제되면 Selector로 개수 확인 후 자동 생성
느슨한 결합 Pod와 Deployment를 레이블로 연결 (직접 참조 없음)
유연한 업데이트 레이블만 변경하면 관리 대상에서 제외 가능

Label 사용 예제

Deployment에서 Label 활용:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx # "app=nginx" 레이블을 가진 Pod를 관리
  template:
    metadata:
      labels:
        app: nginx # 생성되는 Pod에 레이블 부여
        env: production
        tier: frontend
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

Selector와 Label의 일치:

실습:

# Deployment 생성
kubectl apply -f nginx-deployment.yaml

# Pod 확인 (3개 생성됨)
kubectl get pods --show-labels

# Pod 하나 삭제
kubectl delete pod <pod-name>

# 즉시 새 Pod 생성 확인 (Selector 덕분에 자동 복구)
kubectl get pods --show-labels

Label 기반 조회:

# 특정 레이블을 가진 Pod 조회
kubectl get pods -l app=nginx

# 여러 레이블 조건
kubectl get pods -l app=nginx,env=production

# 레이블 표시
kubectl get pods --show-labels

# 레이블로 필터링하여 삭제
kubectl delete pods -l env=development

출력 예시:

NAME                                READY   STATUS    LABELS
nginx-deployment-7d64f8d4c9-abc12   1/1     Running   app=nginx,env=production,tier=frontend
nginx-deployment-7d64f8d4c9-def34   1/1     Running   app=nginx,env=production,tier=frontend
nginx-deployment-7d64f8d4c9-ghi56   1/1     Running   app=nginx,env=production,tier=frontend

Label Selector 표현식:

Selector 연산자:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Equality-based (등호 기반)]
    app = nginx          # app이 nginx인 것
    env != production    # env가 production이 아닌 것

[Set-based (집합 기반)]
    env in (prod, qa)         # env가 prod 또는 qa인 것
    tier notin (frontend)     # tier가 frontend가 아닌 것
    app                       # app 레이블이 존재하는 것
    !version                  # version 레이블이 없는 것

Annotation 사용 예제

Deployment에 Annotation 추가:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  annotations:
    kubernetes.io/change-cause: "Update nginx to v1.25"
    description: "Production web server for main site"
    contact: "devops@example.com"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9113"
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

Annotation 활용 예시:

# Annotation 확인
kubectl describe deployment nginx-deployment

# 롤아웃 히스토리 (change-cause annotation 활용)
kubectl rollout history deployment nginx-deployment

출력 예시:

REVISION  CHANGE-CAUSE
1         Update nginx to v1.25
2         Update nginx to v1.26
3         Rollback to v1.25

참고 자료

공식 문서:

커뮤니티: